#include <iostream>
#include "Thread.hpp"
#include "BlockQueue.hpp"
#include <unistd.h>
#include <vector>
#include <time.h>
#include <sys/types.h>
using namespace ThreadMoudle;

using func_t=std::function<void()>;
using BQ=BlockQueueMoudle::Blockqueue<func_t>;
const int N = 20;

int ticketnum = 10;

int gap = 20;






void Log()
{
    int cnt = 5;
    while(cnt--)
    {
        char time_str[50];
        time_t now = time(nullptr);
        tm* local_time = localtime(&now);
        
        // 格式化日期时间
        sprintf(time_str, "[LOG:当前时间: %04d-%02d-%02d %02d:%02d:%02d]\n",
                local_time->tm_year + 1900,  // 年份需要加1900
                local_time->tm_mon + 1,      // 月份从0开始，需要加1
                local_time->tm_mday,
                local_time->tm_hour,
                local_time->tm_min,
                local_time->tm_sec);
        std::cout <<  time_str << std::endl;
    }
}

void Message()
{
    int cnt = 5;
    while(cnt--)
    {
        char str[50];
        
        // 格式化日期时间
        sprintf(str, "Ciallo～(∠・ω ∠)⌒☆\n");
        

        for(int i= 1 ;i <= (rand()%70) ; ++i)
        std::cout<<' ';

        std::cout <<  str << std::endl;
    }
}


func_t func_arr[] = {Log,Message};


void Consumer(BQ* bq)
{
    while(true)
    {
        func_t data;
        // 1. 从bq拿到数据
        bq->Pop(&data);
        
        // 2.做处理
        printf("Consumer, 消费了一个数据\n");
        data();

    }
}

void Producer(BQ* bq)
{

    func_t data;
    while(true)
    {
        // 1. 从外部获取数据
        sleep(2);
        data = func_arr[rand()%2];
        // 2. 生产到bq中
        bq->Equeue(data);

        printf("producter 生产了一个数据\n");


    }
}

int main()
{
    std::vector<Thread<BQ*>> threads;
    BQ* bq = new BQ;

    for(int i= 1; i <= 3 ; ++i)
    threads.emplace_back(Consumer,bq);

    for(int i = 1 ; i <= 4 ; ++i)
    threads.emplace_back(Producer,bq);


    for(auto& t : threads)
    t.Start();
    for(auto& t : threads)
    {
        int n =t.Join();
        std::cout<<"join "<<t.Name()<<" = "<<n<<std::endl;
    }

    return 0;
}


